<template>
  <el-dialog
    :title="isEdit ? '编辑部门' : '新增部门'"
    :visible="showDialog"
    width="600px"
    @close="onClose"
  >
    <el-form ref="deptForm" label-width="100px" size="mini" :model="deptForm" :rules="rules">
      <el-form-item label="部门名称" prop="name">
        <el-input v-model="deptForm.name" />
      </el-form-item>
      <el-form-item label="部门编码" prop="code">
        <el-input v-model="deptForm.code" />
      </el-form-item>
      <el-form-item label="部门负责人" prop="managerId">
        <el-select v-model="deptForm.managerId" placeholder="请选择负责人">
          <el-option
            v-for="item in managers"
            :key="item.id"
            :label="item.username"
            :value="item.id"
          />
        </el-select>
      </el-form-item>
      <el-form-item label="部门介绍" prop="introduce">
        <el-input v-model="deptForm.introduce" type="textarea" />
      </el-form-item>
      <div style="text-align: center;">
        <el-button v-if="!isEdit" type="primary" size="mini" @click="newDept">确认</el-button>
        <el-button v-else type="primary" size="mini" @click="updateDept">确认</el-button>
        <el-button size="mini" @click="onClose">取消</el-button>
      </div>
    </el-form>
  </el-dialog>
</template>

<script>
import {
  getManagerList,
  getDepartments,
  addNewDepartment,
  getDepartmentData,
  updateDepartment
} from '@/api/department'

export default {
  // 定义组件入参的地方
  props: {
    // 控制弹框是否显示
    showDialog: {
      type: Boolean,
      default: false
    },
    pid: {
      type: Number,
      default: 0
    }
  },
  data() {
    // 定义一个函数，这个函数专门返回一个用于 validate 的校验函数
    const createValidator = (key, msg) => {
      // console.log(this) // 这个this就是当前组件实例对象
      // 返回一个校验函数
      return async(rule, value, callback) => {
        let list = await getDepartments()
        // 如果此时是编辑状态的
        // 那么 list 里面就不应该有自己
        // 做什么? 把自己排除出去
        // 怎么判断是自己？当前节点的 id 在 list 找到了，就说名找到的节点就是自己 ==> 排除
        // 排除重新换一个说话：从 list 中把自己过滤掉 ==> filter
        // filter 是组件的方法，返回一个过滤之后的新数组 ==> 回调函数如果为 true 就保留，否则就滤掉
        // 怎么判断实在编辑状态下？this.deptForm.id 值是否存在 存在就是编辑状态，不存在就是新增
        // 因为编辑状态的时候，获取的节点（部门详情）信息中是有 id 字段的，而新增的时候是没有 id 字段的
        if (this.deptForm.id) {
          list = list.filter(item => item.id !== this.deptForm.id)
        }
        const item = list.find(item => item[key] === value)
        item ? callback(new Error('部门' + msg + '已存在')) : callback()
      }
    }

    return {
      // 部门负责人列表
      managers: [],
      deptForm: this.createDefaultFormData(),
      rules: {
        code: [
          { required: true, message: '部门编码不能为空', trigger: 'blur' },
          { min: 2, max: 10, message: '部门编码长度 2 ~ 10个字符', trigger: 'blur' },
          {
            validator: createValidator('code', '编码'),
            trigger: 'blur'
          }
        ],
        name: [
          { required: true, message: '部门名称不能为空', trigger: 'blur' },
          { min: 2, max: 10, message: '部门名称长度 2 ~ 10个字符', trigger: 'blur' },
          {
            validator: createValidator('name', '名称'),
            trigger: 'blur'
            // validator: async(rule, value, callback) => {
            //   // 1. 拉取最新的部门列表
            //   // 2. 从部门列表数据中查找item.name === value 的项
            //   // 3. 根据查找结果（有：表示重复了）调用 callback
            //   const list = await getDepartments()
            //   const item = list.find(item => item.name === value)
            //   console.log(item)
            //   // 根据 item 是否为 undefined 确认部门名称是否存在
            //   item ? callback(new Error('部门名称已存在')) : callback()
            // },
          }
        ],
        managerId: [
          { required: true, message: '部门负责任不能为空', trigger: 'blur' }
        ],
        introduce: [
          { required: true, message: '部门介绍不能为空', trigger: 'blur' },
          { min: 1, max: 100, message: '部门介绍长度 1 ~ 100个字符', trigger: 'blur' }
        ]
      }
    }
  },
  computed: {
    isEdit() {
      return !!this.deptForm.id
    }
  },
  created() {
    this.getManagers()
  },
  methods: {
    createDefaultFormData() {
      return {
        code: '',
        introduce: '',
        managerId: '',
        name: '',
        pid: ''
      }
    },
    async getManagers() {
      this.managers = await getManagerList()
      // console.log(this.managers)
    },
    // 获取节点详情
    async getDepartmentDetail(id) {
      // 调接口，获取当前节点的详情，并回显到表单中，供用户编辑
      const res = await getDepartmentData(id)
      // console.log(res)
      // 回显数据：就是给 表单绑定的数据对象 赋值为 返回对象

      // 对 data 中一个已有的数据/字段进行重新赋值的时候，新的值也是响应式的
      this.deptForm = res
      // heima 是不是响应式的数据？ 不是响应式的数据
      // this.deptForm.heima = 123
      // 怎么解决上面的问题，让 heima 称为新的属性，并且是响应式？？
      // this.$set(this.deptForm, 'heima', 123)
      // 一言以蔽之：重新赋值是响应式的，新增属性不是响应式的，可以使用 this.$set 方法把新增属性也变成响应式的

      // this.deptForm.id = res.id
      // this.deptForm.code = res.code
      // this.deptForm.name = res.name
      // this.deptForm.introduce = res.introduce
      // this.deptForm.managerId = res.managerId
      // this.deptForm.pid = res.pid
    },
    onClose() {
      // 应该让 showDialog = false
      // 这种事件名是固定格式的
      // update:props属性名
      this.deptForm = this.createDefaultFormData()
      this.$emit('update:showDialog', false)
      // 关闭弹框以后，记着要重置表单的数据
      this.$refs.deptForm.resetFields()
    },
    upsertDept(fn) {
      this.$refs.deptForm.validate()
      // .then(() => {
      //   // 这一步，根据不同的功能调用不能函数
      //   fn()
      // })
        .then(fn)
        .then(() => {
          this.$message.success('添加子部门成功')
          this.$emit('done')
          this.onClose()
        })
    },
    // 新增部门
    newDept() {
      // this.$refs.deptForm.validate()
      // .then(() => {
      //   const postData = { ...this.deptForm, pid: this.pid }
      //   return addNewDepartment(postData)
      // })
      // .then(() => {
      //   this.$message.success('添加子部门成功')
      //   this.$emit('done')
      //   this.onClose()
      // })
      this.upsertDept(() => {
        const postData = { ...this.deptForm, pid: this.pid }
        return addNewDepartment(postData)
      })
    },
    // 编辑。更新部门详情
    updateDept() {
      // this.$refs.deptForm.validate()
      // .then(() => {
      //   return updateDepartment(this.deptForm)
      // })
      // .then(() => {
      //   this.$message.success('添加子部门成功')
      //   this.$emit('done')
      //   this.onClose()
      // })
      this.upsertDept(() => {
        return updateDepartment(this.deptForm)
      })
    }
    // onOk() {
    //   // 1. 先进行表单的手动校验
    //   this.$refs.deptForm.validate(async isOk => {
    //     // console.log(isOk)
    //     if (!isOk) return
    //     // 能往下执行，说明校验是通过
    //     // 判断当前的操作类型：新增 还是 编辑
    //     // 通过 this.deptForm.id 去判断
    //     if (this.deptForm.id) {
    //       // 编辑
    //       await updateDepartment(this.deptForm)
    //       this.$message.success('部门详情更新成功')
    //     } else {
    //       // 新增
    //       // 0.1 组装请求数据
    //       const postData = { ...this.deptForm, pid: this.pid }
    //       // 0.2 调接口
    //       await addNewDepartment(postData)
    //       // 0.3 请求成功，给用户提示
    //       this.$message.success('添加子部门成功')
    //     }
    //     // 0.4 告诉父组件，我干完了
    //     this.$emit('done')
    //     // 0.5 关闭当前的弹框
    //     this.onClose()
    //   })
    // }
  }
}
</script>

<style>

</style>
